﻿#ifndef QLIB_HEADER_CIRCLE
#define QLIB_HEADER_CIRCLE

#include "qlib/core/array.h"
#include "qlib/core/object.h"
#include "qlib/geo/polygon.h"
#include "qlib/layout/repetition.h"
#include "qlib/layout/property.h"

namespace qlib {

enum struct GeoPartType;

class Circle;
using CirclePtrArray = std::vector<std::shared_ptr<Circle>>;
using CirclePtrArrayMap = std::unordered_map<Tag, CirclePtrArray, Tag::Hash>;
// 0: 中心， 1: 顶点， 2: 边， 3: 边中点，4: box顶点, 5: box边, 6: box边中心
using CircleParts = std::tuple<Vec2d, Vec2dArray, std::vector<Vec2dArray>, Vec2dArray, Vec2dArray, std::vector<Vec2dArray>, Vec2dArray>;

class QLIB_API Circle {
 public:
  Circle();
  Circle(Vec2d _center, double _radius, double _tolerance = 1e-3, uint32_t _layer = 0, uint32_t _datatype = 0);

  using s_ptr = std::shared_ptr<Circle>;
  template <typename... Args>
  static s_ptr create(Args... args) {
    return std::make_shared<Circle>(args...);
  }
  // template <>
  static s_ptr create() {
    return std::make_shared<Circle>();
  }
  static s_ptr create(const Circle& value) { return std::make_shared<Circle>(value); }

  s_ptr copy() const;
  void init(Vec2d _center, double _radius, double _tolerance = 1e-3, uint32_t _layer = 0, uint32_t _datatype = 0);

  Polygon::s_ptr to_polygon() const;
  Vec2dArray bounding_box_points() { return box_to_points(bounding_box()); };
  Vec2dArray bounding_box();

  void scale(double s);
  void rotate(double angle, Vec2d center);
  void mirror(Vec2d p0, Vec2d p1);
  void translate(double dx, double dy);
  void transform(double magnification, bool x_reflection, Vec2d origin);

  // 部分选择
  CircleParts get_parts();
  Vec2dArray query_parts(GeoPartType type, uint32_t id);

  // 渲染
  Vec2dArray render_aabb();
  Vec2dArray render_poly();
  Vec2dArray render_absorp();

  Vec2dArray points;
  Vec2d center;
  double radius;

  double tolerance;

  uint32_t layer;
  uint32_t datatype;

  Vec2dArray box;

  PropertyArray properties;
  Repetition repetition;
};

}  // namespace qlib

#endif